home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 July: Mac OS SDK / Dev.CD Jul 97 SDK1.toast / Development Kits (Disc 1) / QuickDraw GX / Programming Stuff / Sample Code / Printing Samples / Applications… / Getting Started w⁄GX ƒ / Getting Started GX - shapes.c < prev    next >
Encoding:
Text File  |  1996-04-27  |  30.9 KB  |  948 lines  |  [TEXT/KAHL]

  1. /**
  2.  --
  3.  --
  4.  --        App:        Getting Started w/QD GX (WWDC)
  5.  --
  6.  -- 
  7.  --        Version:    1.0     4/93:    added all of the calls required to support the "Getting 
  8.  --                                    Started with QuickDraw™ GX" session at the WWDC '93     
  9.  --
  10.  --                            8/93:    updated file to work with the ß2 "GXified" interface files
  11.  --
  12.  --                               12/93:    updated for b3. - dmh & pla
  13.  --                                3/94:    corrected usage of GXSetShapeAttributes. - dmh
  14.  --                                8/94:    universalized. - dmh
  15.  --            
  16.  --            
  17.  --        File:        Getting Started GX - shapes.c 
  18.  --
  19.  --        Comments:    This code demonstrates creates, manipulates, and draws all of the QuickDraw
  20.  --                    GX shapes used in this app. This is the same code which was used during the
  21.  --                    "Getting Started With QuickDraw GX" WWDC '93 session.
  22.  --
  23.  --                    This application will also support multiple windows. We present two menus
  24.  --                    to the user to draw into the contents of the window. The "Graphics" menu
  25.  --                    allows the user to create a platinum rectangle and rotate a text shape ("QD GX")
  26.  --                    from the lower left corner 45 degrees. The font used within the text shape
  27.  --                    is the "Skia" font. This font contains font variation information. This information
  28.  --                    allows us to change the various axes within the font to receive different
  29.  --                    effects. In our case, we retrieve information regarding the 'wght' axis of the
  30.  --                    font and set it to the maximum width allowed. By setting the 'wght' axis to the
  31.  --                    maximum, we receive nice fat letters. Each letter of the text shape is colored
  32.  --                    in a different CMYK color. We will also outline each character in black. Finally, 
  33.  --                    we add a star pattern to the "X". 
  34.  --
  35.  --                    As each letter is drawn, you can see the "gxAndMode" transfer mode applied as 
  36.  --                    the characters overlap.
  37.  --                    
  38.  --                    The second menu "Typography", creates and manipulates a layout shape. The first 
  39.  --                    menu item will create the layout shape. Once you have created the layout shape,
  40.  --                    you will recieve the "as" ligature in "Nasty", swashes for the "C", "N", and "D",
  41.  --                    the final form of "e" in "Dude", and the automatic kerning of "WAVE".
  42.  --
  43.  --                    For all of the layout effects to work, you need the following fonts installed into 
  44.  --                    your system:
  45.  --
  46.  --                    • Hoefler (this font will be automatically installed, if you use the Installer Script)
  47.  --                    • Skia
  48.  --                    • HonMincho
  49.  --                    • Times
  50.  --
  51.  --                    All of the fonts listed above (except Hoefler), can be found in the "Testing Fonts"
  52.  --                    Folder contained within the "• Open Me First! •" folder. If these fonts are _not_
  53.  --                    installed, you will recieve font substitution, and you will receive interesting
  54.  --                    characters when the Kanji text is drawn.
  55.  --
  56.  --                    The next item allows you to add two-byte Kanji text to the layout shape. The last
  57.  --                    item allows you to perspect the layout shape.
  58.  --
  59.  --
  60.  --        Components:    Getting Started GX - main.c
  61.  --                    Getting Started GX - main.h
  62.  --                    Getting Started GX - shapes.c
  63.  --                    Getting Started GX - printing.c
  64.  --                    Getting Started GX - misc.c
  65.  --                    Getting Started QD GX.π.rsrc
  66.  --
  67.  --                    The file titled: "Getting Started GX - main.c" contains the code required
  68.  --                    to intialize and tear down the QuickDraw GX world, and the event loop.
  69.  --
  70.  --                    The file titled: "Getting Started GX - printing.c" contains the code required
  71.  --                    to print the contents of the window.
  72.  --        
  73.  --        History:    4/93    New        PLA
  74.  --                    12/93    Updated to use the new/changed line layout feature constants with QD GX ß3 PLA    
  75.  --        
  76.  --        QuickDraw GX
  77.  --        Libraries
  78.  --        Used:        This application uses the following QuickDraw GX library code files:
  79.  --                    "color library.c", "font library.c", "graphics debug library.c",
  80.  --                    "layout library.c", "qd library.c", "shape library.c", 
  81.  --                    "transferMode library.c", and "transform library.c". 
  82.  --        
  83.  --        
  84.  --        Notes:        1) Print this file in landscape for the best results
  85.  --                    2) If you are using THINK C v6.x, I have added THINK markers to navigate the code.
  86.  --                    3) This code was adapted from the "Banana Jr." QuickDraw GX sample.
  87.  --
  88.  --
  89.  --        Author:        Pete "Luke" Alexander
  90.  --                    Developer Technical Support
  91.  --                    AppleLink: DEVSUPPORT
  92.  --
  93.  --        
  94.  --        ©1992 - 1993  Apple Computer, Inc. 
  95.  --        All rights reserved.
  96.  --
  97.  **/
  98.  
  99.  
  100. #include <events.h>
  101. #include <memory.h>
  102. #include <windows.h>
  103.  
  104. #include "FontLibrary.h"
  105. #include "GraphicsLibraries.h"
  106. #include <GXEnvironment.h>
  107. #include <GXErrors.h>
  108. #include "QDLibrary.h"
  109. #include <GXPrinting.h>
  110.  
  111. #include "Getting Started GX - main.h"
  112.  
  113. #include "LayoutLibrary.h"
  114. #include <GXLayout.h>
  115. #include <LayoutFeatureConstants.h>
  116.  
  117. //
  118. //    Set up the title and size of the window
  119. //
  120. Str255         gWindowTitle = "\p Various Shapes...";
  121. Rect         gWindowQDRect  = {50, 10, 470, 590};
  122.  
  123.  
  124. //
  125. //    If gDebugging = TRUE, graphics library errors and notices will be posted.  This functionality will only work with 
  126. //    the "debugging" version of the QuickDraw GX init.  If this version of the init is not installed, nothing bad will happen, 
  127. //    but these  functions will not work.
  128. //
  129. Boolean        gDebugging = true;
  130.  
  131. //
  132. //    Set  "gGiveMeValidation" to TRUE, if you will receive run-time validation.
  133. //
  134. Boolean        gGiveMeValidation = true;
  135.  
  136.  
  137. //
  138. //    gGraphicsHeapSize sets the size of the graphics heap created by calling the GXNewGraphicsClient routine
  139. //    in main () within the Getting Started GX - main.c file.  You can determine the amount of graphics heap
  140. //    required by using GraphicsBug.I'm giving it 500K, since we need a bunch if we have several windows open.
  141. //
  142. long        gGraphicsHeapSize = 500;
  143.  
  144. gxFont        gtheSkiaFont;
  145.  
  146.  
  147.  
  148. /*------ DoInitialization ---------------------------------------------------------------------------------*/
  149. //
  150. //    In this function we create and gxInitialize the the private document structure for a new window.  This
  151. //    structure contains the print job and the shape which is drawn in the window.  We store this data in
  152. //    a handle and hang it off the window's refCon field for easy retrieval.  By doing this, rather than using
  153. //    globals, we can create many windows containing unique print jobs and shapes. 
  154. //
  155. OSErr DoInitialization(wind)
  156. WindowPtr wind;
  157. {
  158.     OSErr        err;
  159.     gxJob        docJob;
  160.     gxShape        docPage;
  161.     TH_Doc        windDoc;
  162.  
  163.     //
  164.     //     Create the page shape. We set the unique items attribute to make sure that each item added to the
  165.     //     picture has a unique reference. 
  166.     //
  167.     docPage = GXNewShape(gxPictureType);
  168.     GXSetShapeAttributes(docPage, GXGetShapeAttributes(docPage)|gxUniqueItemsShape);
  169.     
  170.     //
  171.     //     Create a print job for this document.  This will be the same as the system default until the user
  172.     //     goes through the dialogs for Page Setup or Print…
  173.     //
  174.     err = GXNewJob(&docJob);
  175.  
  176.     //
  177.     //     If there are no errors, create a handle the size of our document structure and store the print job and page shape
  178.     //     in it.  Store the handle in the window's refCon field so that we can get at it.  (Note that the utility routines
  179.     //     "GetDocJob" and "GetDocShape" can be used to do this easily.
  180.     //
  181.     if (!err)
  182.     {
  183.         windDoc = (TH_Doc) NewHandleClear(sizeof(T_Doc));
  184.  
  185.         if (!windDoc)
  186.             err = MemError();
  187.         else
  188.         {
  189.             (*windDoc)->docJob = docJob;
  190.             (*windDoc)->docPage = docPage;
  191.             ((WindowPeek) wind)->refCon = (long) windDoc;
  192.         }
  193.  
  194.     //
  195.     //    If there are no errors, install our override for gxPrintingEvent (which will
  196.     //    allow us to update our windows as the printing dialogs are moved around.
  197.     //
  198.     GXInstallApplicationOverride(docJob, gxPrintingEventMsg, NewGXPrintingEventProc(MyPrintingEventOverride));
  199.     }
  200. }
  201.  
  202.  
  203. /*------ DoDraw ---------------------------------------------------------------------------------------*/
  204. //
  205. //    We retrieve the GX picture attached the window and draw the contents of the window.
  206. // 
  207. void DoDraw(wind)
  208. WindowPtr wind;
  209. {
  210.      GXDrawShape (GetDocShape(wind));
  211. }
  212.  
  213.  
  214.  
  215. /*------ CreateNewLayoutShape -------------------------------------------------------------------------*/
  216. //
  217. //    We create a layout shape and added it ot the GX picture attached to the front window.
  218. // 
  219.  
  220. void CreateNewLayoutShape(WindowPtr wind)
  221. {
  222.     gxShape                thePage;
  223.     char                 *sampleText = "Catch the Nasty WAVE, Dude";
  224.     gxShape             tempLayoutShape;
  225.     gxPoint             layoutPostion = {ff(10), ff(65)};
  226.     gxRunControls        runControls;
  227.     gxRunFeature        runFeatures[3];
  228.     gxStyle                styles[3];
  229.     short                totalLengthOfLayout, 
  230.                         lengthsArray[3],
  231.                         loop;
  232.  
  233.     //
  234.     //    Retreive the GX picture attached to the front window.
  235.     //
  236.     thePage = GetDocShape(wind);
  237.  
  238.     //
  239.     //    We start by intializing the layout run controls to their default values.
  240.     //
  241.     InitializeRunControls(&runControls);
  242.         
  243.  
  244.     //
  245.     //    We need to create the style which will be used for the first run of text within our
  246.     //    layout shape: "Catch the Nasty WAVE, Dude". Within a layout shape, you have the ability to have
  247.     //    multiple runs of text. Each run can use: a different font, text size, run features,
  248.     //    run controls.
  249.     //    
  250.     //    In the case of our first run of text, we want to use Hoefler Italic and a text size of 36.
  251.     //    We set the run controls to their default setting. 
  252.     //
  253.     styles[0] = NewLayoutStyle((char *)"\pHoefler Italic", ff(36), 0, &runControls, nil, 0, nil);
  254.  
  255.  
  256.     //
  257.     //    Next, we want to turn on a couple of run features within this run of text. We start by
  258.     //    enabling the "as" ligature in "Nasty". We tell gxLine layout that we want to set the 
  259.     //    featureType of our run control to enable the ligature capabilities of Hoefler Italic, and
  260.     //    we then enable the "as" ligature. 
  261.     //
  262.     runFeatures[0].featureType = ligatureType;
  263.     runFeatures[0].featureSelector = ligatureRareOnSelector;
  264.  
  265.  
  266.     //
  267.     //    !! •• ß3 Change •• !!
  268.     //
  269.     //    The next thing we need to tell line layout to do is enable the swash capabilities of our 
  270.     //    "C" and "N" characters contained within the first run of text. These swashes are part of the 
  271.     //    Hoefler Italic font. We acheive this goal by setting the runFeatures featureType
  272.     //    to characterAlternativesType with a featureSelector of 1.
  273.     //
  274.     //    This is an example were the characterAlternativesType feature is font dependent. Each TrueType
  275.     //    GX font can contain 0 or more additional character alternatives selectors defined by a font.
  276.     //    In the case of the Hoefler Italic font, the 1st feature enables the "C" and "N" swashes of 
  277.     //    each word.
  278.     //
  279.     runFeatures[1].featureType = characterAlternativesType;
  280.     runFeatures[1].featureSelector = 1;
  281.     
  282.     //
  283.     //    After we have created the run features we need, we set the run features of our
  284.     //    style to use them.
  285.     //
  286.     GXSetStyleRunFeatures(styles[0], 2, runFeatures);
  287.     
  288.     //     
  289.     //    In the second style we need to create is for the "WAVE!" run. For this run of text, 
  290.     //    we want the font to be Times Roman, 38 point text size, and use the default run 
  291.     //    controls. This style will also give us automatic kerning of the run.
  292.     //
  293.     styles[1] = NewLayoutStyle((char *)"\pTimes Roman", ff(38), 0, &runControls, nil, 0, nil);
  294.     
  295.  
  296.     //
  297.     //    The final style we need to create is used by the last run of text "dude". 
  298.     //
  299.     styles[2] = NewLayoutStyle((char *)"\pHoefler Italic", ff(34), 0, &runControls, nil, 0, nil);
  300.  
  301.     //
  302.     //    The run features used for the style reference by the last run of text will
  303.     //    enable the final form of "e" in "dude". We enable these smartSwashType feature and
  304.     //    turn on the final form of "e".
  305.     //
  306.     runFeatures[2].featureType = smartSwashType;
  307.     runFeatures[2].featureSelector = lineFinalSwashesOnSelector;
  308.     
  309.     //
  310.     //    Update the style used for this run of text to use the our run features which
  311.     //    enable the final form "e".
  312.     //
  313.     GXSetStyleRunFeatures(styles[2], 3, runFeatures);
  314.     
  315.     //
  316.     //    The "lengthsArray" defines the length of each run of text used within our layout shape. 
  317.     //    In our case, the first run of text is 16 characters, the second run is 4 characters,
  318.     //    and the final run is 5 characters.
  319.     //
  320.     lengthsArray[0] = 15;    lengthsArray[1] = 6;  lengthsArray[2] = 5;
  321.  
  322.     totalLengthOfLayout = 26;
  323.  
  324.     //
  325.     //    We now update our layout shape to include our 2 new styles. When our layout shape
  326.     //    is drawn, the "C" and "N" swashes, "as" ligature, and the kerning of "WAVE!" will
  327.     //    appear.
  328.     //
  329.     tempLayoutShape = GXNewLayout(1, &totalLengthOfLayout, (void *) &sampleText, 
  330.                                   3, lengthsArray, styles, 0, nil, nil, nil, &layoutPostion);
  331.  
  332.     GXSetPictureParts(thePage, 0, 0, 1, &tempLayoutShape, nil, nil, nil);
  333.     GXDisposeShape(tempLayoutShape);
  334.     
  335.  
  336.       //
  337.       //    We can now dispose of our styles because they have been added into our layout shape.
  338.       //    They are no longer needed....
  339.      //
  340.     for (loop = 0; loop < 3; loop++) 
  341.       GXDisposeStyle(styles[loop]);
  342.  
  343.  
  344.      //
  345.     // Invalidate the window's portRect so that everything gets updated.
  346.      //
  347.     SetPort(wind);
  348.     InvalRect(&wind->portRect);
  349. }
  350.  
  351.  
  352.  
  353.  
  354. /*------ AddKanjiToLayout -----------------------------------------------------------------------------*/
  355. //
  356. //    This removes single byte roman version of "WAVE", and replaces it with the two-byte Kanji version.
  357. //
  358. void AddKanjiToLayout(WindowPtr wind)
  359. {
  360.     gxShape        thePage;
  361.     gxShape        tempLayoutShape;
  362.     gxShape        layoutShapeFromPicture;
  363.     gxStyle        kanjiStyle;
  364.     char         *kanjiSampleText = "îgòQ";
  365.     short        lengthsArray[1];
  366.  
  367.     //
  368.     //    Retreive the GX picture attached to the front window.
  369.     //
  370.     thePage = GetDocShape(wind);
  371.  
  372.     //
  373.     //    Retrieve the layout shape from the picture and make a copy of it.
  374.     //
  375.     GXGetPictureParts(thePage, 1, 1, &layoutShapeFromPicture, nil, nil, nil);
  376.     tempLayoutShape = GXCopyToShape (nil, layoutShapeFromPicture);
  377.     
  378.     //
  379.     //    Create a new style which uses the "HonMincho Medium" font and set the encoding. If
  380.     //    you do not set the encoding for this style, QD GX will not know how to create
  381.     //    the characters passed, thereby using the characters in a different manner than
  382.     //    you intended.
  383.     //
  384.     kanjiStyle = NewLayoutStyle((char *)"\pHonMincho Medium", ff(39), 0, nil, nil, 0, nil);
  385.     GXSetStyleEncoding (kanjiStyle, gxMacintoshPlatform, gxJapaneseScript, gxJapaneseLanguage);
  386.  
  387.     //
  388.     //    We now insert (i.e. replace the roman characters) the new Kanji characters on top 
  389.     //    of the roman "WAVE". We know the roman characters start at byte location 16 and
  390.     //    end at 21.
  391.     //
  392.     lengthsArray[0] = 4;
  393.     
  394.     GXSetLayoutParts(tempLayoutShape, 16, 21, 1, lengthsArray,(void *) &kanjiSampleText, 
  395.                      1, lengthsArray, &kanjiStyle, 0, nil, nil);
  396.  
  397.     GXDisposeStyle(kanjiStyle);
  398.     
  399.     //
  400.     //    We move our newly modified layout shape and add it to our picture.
  401.     //
  402.     GXMoveShape (tempLayoutShape, 0, ff(75));
  403.     GXValidateShape (tempLayoutShape);
  404.     
  405.     GXSetPictureParts(thePage, 2, 0, 1, &tempLayoutShape, nil, nil, nil);
  406.     GXDisposeShape(tempLayoutShape);
  407.  
  408.  
  409.     //
  410.     // Invalidate the window's portRect so that everything gets updated.
  411.     //
  412.     SetPort(wind);
  413.     InvalRect(&wind->portRect);
  414. }
  415.  
  416.  
  417. /*------ PerspectLayout -------------------------------------------------------------------------------*/
  418. //
  419. //    Since a layout shape is treated like any other graphics shape, we can perspect it and preserve
  420. //    all of the layout features when enabled when we created the shape, therefore this function will
  421. //    perspect the current layout shape.
  422. //
  423. void PerspectLayout(WindowPtr wind)
  424. {
  425.     gxShape        thePage;
  426.     gxShape        tempLayoutShape;
  427.     gxShape        layoutShapeFromPicture;
  428.     gxRectangle layoutBounds;
  429.     gxMapping    layoutMapping;
  430.     Fixed         x, y;
  431.  
  432.     //
  433.     //    Retreive the GX picture attached to the front window.
  434.     //
  435.     thePage = GetDocShape(wind);
  436.  
  437.     //
  438.     //    Retrieve the layout shape from the picture and make a copy of it.
  439.     //
  440.     GXGetPictureParts(thePage, 2, 1, &layoutShapeFromPicture, nil, nil, nil);
  441.     tempLayoutShape = GXCopyToShape (nil, layoutShapeFromPicture);
  442.  
  443.     //
  444.     // Determine the center of our layout shape.
  445.     //
  446.     GXGetShapeBounds(tempLayoutShape, 0L, &layoutBounds);
  447.     x = layoutBounds.left + layoutBounds.right >> 1;
  448.     y = layoutBounds.top + layoutBounds.bottom >> 1;
  449.         
  450.     //
  451.     //    We scale the layout to enable us to get a better visual effect when we prespect it, 
  452.     //    and we move it to prevent it fonr drawing on top of the latest layout shape added 
  453.     //    to the picture.
  454.     //    
  455.     GXScaleShape(tempLayoutShape, ff(2), ff(2), 0, 0);
  456.     GXMoveShape(tempLayoutShape, 0, ff(100));
  457.  
  458.     //
  459.     //    Retrieve the gxMapping of our layout shape and perspect it, pulling along and
  460.     //    down the x-axis.
  461.     //
  462.     GXGetShapeMapping(tempLayoutShape, &layoutMapping);
  463.     layoutMapping.map[0][2] = ff(30);
  464.     layoutMapping.map[1][2] = ff(1);
  465.     GXSetShapeMapping(tempLayoutShape, &layoutMapping);
  466.  
  467.     //
  468.     //    Add our newly perspected layout shape to our picture.
  469.     //
  470.     GXSetPictureParts(thePage, 3, 0, 1, &tempLayoutShape, nil, nil, nil);
  471.     GXDisposeShape(tempLayoutShape);
  472.     
  473.             
  474.     //
  475.     //     Invalidate the window's portRect so that everything gets updated.
  476.     //
  477.     SetPort(wind);
  478.     InvalRect(&wind->portRect);
  479. }
  480.  
  481.  
  482. /*------ CreateABlackRectangle ------------------------------------------------------------------------*/
  483. //
  484. //    We want to create a black rectangle. Within GX, you need to define the geometry and create a shape.
  485. //    You are then ready to draw the particular shape.
  486. //
  487. void CreateABlackRectangle (WindowPtr wind)
  488. {
  489.     gxShape            thePage;
  490.     gxShape            tempRectShape;
  491.     gxRectangle     rectGeometry = {ff(70), ff(70), ff(280), ff(275)};    
  492.  
  493.     //
  494.     //    Retreive the GX picture attached to the front window.
  495.     //
  496.     thePage = GetDocShape(wind);
  497.  
  498.     //
  499.     //    Create the rectangle which is defined by the rectangular geometry contained within 
  500.     //    "rectGeometry" and add it to our picture.
  501.     //
  502.      tempRectShape = GXNewRectangle(&rectGeometry); 
  503.      GXSetPictureParts(thePage, 0, 0, 1, &tempRectShape, nil, nil, nil);
  504.     GXDisposeShape(tempRectShape);  
  505.  
  506.     //
  507.     //     Invalidate the window's portRect so that everything gets updated.
  508.     //
  509.     SetPort(wind);
  510.     InvalRect(&wind->portRect);
  511. }
  512.  
  513.  
  514. /*------ ColorTheRectangle ----------------------------------------------------------------------------*/
  515. //
  516. //     We want to color our rectangle a more interesting color to allow the transfer modes we will add to 
  517. //    the text shape to appear, therefore we color our rectangle "platinum". We use the common color
  518. //    library to perform the coloring. In this case, the library creates the platinum color in RGB space.
  519. //
  520. void ColorTheRectangle (WindowPtr wind)
  521. {
  522.     gxShape        thePage;
  523.     gxShape        tempRectShape;
  524.  
  525.     //
  526.     //    Retreive the GX picture attached to the front window.
  527.     //
  528.     thePage = GetDocShape(wind);
  529.     
  530.     //
  531.     //    Get a reference to our black rectangle and change the color to platinum.
  532.     //
  533.     GXGetPictureParts(thePage, 1, 1, &tempRectShape, nil, nil, nil);
  534.     SetShapeCommonColor (tempRectShape, platinum );
  535.  
  536.  
  537.     //
  538.     //     Invalidate the window's portRect so that everything gets updated.
  539.     //
  540.     SetPort(wind);
  541.     InvalRect(&wind->portRect);
  542. }
  543.  
  544.  
  545.  
  546. /*------ CreateAQ -------------------------------------------------------------------------------------*/
  547. //
  548. //    We want to create the first text shape - "Q". So, we need to create the following GX objects:
  549. //    the text shape containing the "Q", the CMYK color used to color "Q", a style which defines the 
  550. //    font, font size, the 'wght', pen width, and pen drawing location.
  551. //
  552. void CreateAQ (WindowPtr wind)
  553. {
  554.     gxShape                thePage;
  555.     gxShape                tempTextShape;
  556.     Fixed                maxVariationValue;
  557.     gxFontVariation        fontVariation;
  558.     long                result;
  559.     
  560.     //
  561.     //    Retreive the GX picture attached to the front window.
  562.     //
  563.     thePage = GetDocShape(wind);
  564.  
  565.     //
  566.     //    Create a new style to contain: the font, font size, the 'wght' axis of the font set to the
  567.     //    maximum value allowed for this font, set the pen size, and the location of the pen when 
  568.     //    drawing.
  569.     //
  570.     gOurStyle = GXNewStyle ();
  571.     
  572.     GXSetStylePen(gOurStyle, ff(2));
  573.     GXSetStyleAttributes(gOurStyle, gxOutsideFrameStyle);
  574.     
  575.     GXSetStyleTextSize(gOurStyle, ff(135));
  576.     gtheSkiaFont = FindPNameFont (gxFullFontName, "\pSkia Regular");
  577.     GXSetStyleFont(gOurStyle, gtheSkiaFont);
  578.     
  579.     result = GXFindFontVariation(gtheSkiaFont, 'wght', nil, nil, &maxVariationValue, nil);
  580.  
  581.     //
  582.     //    If the "result" is good, we proceed to set the "wght" axis to the maximum value. If the 
  583.     //    "result" is bad, this probably means that the "Skia" font has not been installed. In this
  584.     //    case we cannot set the "wght" axis, so we do not and we alert the user. We will be able 
  585.     //    to continue at this gxPoint, but we will not have the fat juicy letters.
  586.     //
  587.     if (result) {
  588.         fontVariation.name     = 'wght';
  589.         fontVariation.value    = maxVariationValue;
  590.     
  591.          GXSetStyleFontVariations(gOurStyle, 1, &fontVariation);
  592.          
  593.     } else  DebugStr ("\p NO 'wght' axis....");
  594.  
  595.     //
  596.     //    Set up as CMYK color space which will used to color all of our text shapes. The "Q" will
  597.     //    be colored in magenta. Each text shape will use a different CMYK color. We change the setting
  598.     //    for our "gTextColor" when we create each new shape.
  599.     //
  600.     gTextColor.space                     = gxCMYKSpace;
  601.     gTextColor.element.cmyk.cyan         = 0x0000;
  602.     gTextColor.element.cmyk.magenta     = 0xffff;
  603.     gTextColor.element.cmyk.yellow         = 0x0000;
  604.     gTextColor.element.cmyk.black         = 0x0000;
  605.     gTextColor.profile                     = nil;
  606.     
  607.     //
  608.     //    Create the "Q", and set it's: style, transfer mode, color, and shape fill.
  609.     //
  610.     tempTextShape = GXNewText (1, (unsigned char*) "Q", &gTextLocation);
  611.      SetShapeCommonTransfer(tempTextShape, gxAndMode);
  612.     GXSetShapeStyle(tempTextShape, gOurStyle);
  613.      GXSetShapeColor(tempTextShape, &gTextColor);
  614.  
  615.     gRotatedTransform = GXNewTransform ();
  616.     GXRotateTransform(gRotatedTransform, -ff(40), ff(200), ff(200));
  617.     GXMoveTransform(gRotatedTransform, ff(40), ff(100));
  618.  
  619.      GXSetPictureParts(thePage, 0, 0, 1, &tempTextShape, nil, nil, &gRotatedTransform);
  620.     GXDisposeShape(tempTextShape);  
  621.  
  622.     //
  623.     //     Invalidate the window's portRect so that everything gets updated.
  624.     //
  625.     SetPort(wind);
  626.     InvalRect(&wind->portRect);
  627. }
  628.                     
  629.                         
  630. /*------ OutlineTheQ ----------------------------------------------------------------------------------*/
  631. //
  632. //    We want to outline our "Q" in black. So, we retrieve a copy of the "Q" from our picture, make
  633. //    a copy, change the shape fill to outline, color the outline back, and add the copy to our picture.
  634. //
  635. void OutlineTheQ (WindowPtr wind)
  636. {
  637.     gxShape        thePage;
  638.     gxShape        tempTextShape;
  639.     gxShape        theQFromThePicture;
  640.  
  641.     //
  642.     //    Retreive the GX picture attached to the front window.
  643.     //
  644.     thePage = GetDocShape(wind);
  645.  
  646.     //
  647.     //    Retrieve the "Q" from our picture and make a copy.
  648.     //
  649.     GXGetPictureParts(thePage, 2, 1, &theQFromThePicture, nil, nil, nil);
  650.     tempTextShape = GXCopyToShape (nil, theQFromThePicture);
  651.  
  652.     //
  653.     //    Set the shape fill to be outline of our "Q", center the pen on the geometry,
  654.     //  and color it black.
  655.     //
  656.     GXSetShapeType(tempTextShape, gxPathType); 
  657.     GXSetShapeFill(tempTextShape, gxClosedFrameFill);
  658.     GXSetShapeStyleAttributes(tempTextShape, gxCenterFrameStyle);
  659.     SetShapeCommonColor(tempTextShape, gxBlack);
  660.     SetShapeCommonTransfer(tempTextShape, gxCopyMode);
  661.  
  662.     //
  663.     //    Add the new outlined "Q" to our picture.
  664.     //
  665.     GXSetPictureParts(thePage, 3, 0, 1, &tempTextShape, nil, nil, nil);
  666.     GXDisposeShape(tempTextShape);  
  667.  
  668.     //
  669.     //     Invalidate the window's portRect so that everything gets updated.
  670.     //
  671.     SetPort(wind);
  672.     InvalRect(&wind->portRect);
  673. }
  674.  
  675.  
  676. /*------ CreateAD -------------------------------------------------------------------------------------*/
  677. //
  678. //    We want to add a "D" to our picture, which is colored a yellow CMYK color, and outline it.
  679. //
  680. void CreateAD (WindowPtr wind)
  681. {
  682.     gxShape                thePage;
  683.     gxShape                tempTextShape;
  684.  
  685.     //
  686.     //    Retreive the GX picture attached to the front window.
  687.     //
  688.     thePage = GetDocShape(wind);
  689.     
  690.     //
  691.     //    Set the CYMK color to be yellow.
  692.     //
  693.     gTextColor.element.cmyk.magenta = 0x0000;
  694.     gTextColor.element.cmyk.yellow = 0xffff;
  695.     
  696.     //
  697.     //    Create the "D", set it's transfer mode to gxAndMode with the transfer mode library, 
  698.     //    and set it's starting location, set the color, attach the style, and set the shape fill.
  699.     //
  700.     gTextLocation.x += ff(75);
  701.      tempTextShape = GXNewText (1, (unsigned char*) "D", &gTextLocation);
  702.     SetShapeCommonTransfer(tempTextShape, gxAndMode);
  703.       GXSetShapeStyle(tempTextShape, gOurStyle);
  704.      GXSetShapeColor(tempTextShape, &gTextColor);
  705.  
  706.     GXSetPictureParts(thePage, 0, 0, 1, &tempTextShape, nil, nil, &gRotatedTransform);
  707.  
  708.     //
  709.     //    Create the outline of the "D", center the pen on the geometry of the outline,
  710.     //    color it black and add it to the picture.
  711.     //
  712.     GXSetShapeType(tempTextShape, gxPathType); 
  713.     GXSetShapeStyleAttributes(tempTextShape, gxCenterFrameStyle);
  714.     GXSetShapeFill(tempTextShape,  gxClosedFrameFill);
  715.     SetShapeCommonColor(tempTextShape, gxBlack);
  716.     SetShapeCommonTransfer(tempTextShape, gxCopyMode);
  717.  
  718.     GXSetPictureParts(thePage, 0, 0, 1, &tempTextShape, nil, nil, &gRotatedTransform);
  719.     GXDisposeShape(tempTextShape);  
  720.  
  721.     //
  722.     //     Invalidate the window's portRect so that everything gets updated.
  723.     //
  724.     SetPort(wind);
  725.     InvalRect(&wind->portRect);
  726. }
  727.  
  728.  
  729.  
  730. /*------ CreateAG -------------------------------------------------------------------------------------*/
  731. //
  732. //    We want to add a "G" to our picture, which is colored a yellow CMYK color, and outline it.
  733. //
  734. void CreateAG (WindowPtr wind)
  735. {
  736.     gxShape                thePage;
  737.     gxShape                tempTextShape;
  738.  
  739.     //
  740.     //    Retreive the GX picture attached to the front window.
  741.     //
  742.     thePage = GetDocShape(wind);
  743.     
  744.     //
  745.     //    Set the CYMK color to be yellow.
  746.     //
  747.     gTextColor.element.cmyk.cyan = 0xffff;
  748.     gTextColor.element.cmyk.yellow = 0x0000;
  749.  
  750.     //
  751.     //    Create the "G", set it's transfer mode to gxAndMode with the transfer mode library, 
  752.     //    and set it's starting location, set the color, attach the style, and set the shape fill.
  753.     //
  754.     gTextLocation.x += ff(75);
  755.      tempTextShape = GXNewText (1, (unsigned char*) "G", &gTextLocation);
  756.     SetShapeCommonTransfer(tempTextShape, gxAndMode);
  757.      GXSetShapeStyle(tempTextShape, gOurStyle);
  758.      GXSetShapeColor(tempTextShape, &gTextColor);
  759.  
  760.     GXSetShapeType(tempTextShape, gxPathType); 
  761.     GXSetPictureParts(thePage, 0, 0, 1, &tempTextShape, nil, nil, &gRotatedTransform);
  762.  
  763.     //
  764.     //    Create the outline of the "G" and add it to the picture.
  765.     //
  766.     GXSetShapeStyleAttributes(tempTextShape, gxCenterFrameStyle);
  767.     GXSetShapeFill (tempTextShape,  gxClosedFrameFill);
  768.     SetShapeCommonColor (tempTextShape, gxBlack );
  769.     SetShapeCommonTransfer(tempTextShape, gxCopyMode);
  770.     
  771.     GXSetPictureParts(thePage, 0, 0, 1, &tempTextShape, nil, nil, &gRotatedTransform);
  772.     GXDisposeShape(tempTextShape);  
  773.  
  774.  
  775.     //
  776.     // Invalidate the window's portRect so that everything gets updated.
  777.     //
  778.     SetPort(wind);
  779.     InvalRect(&wind->portRect);
  780. }
  781.  
  782.  
  783.  
  784. /*------ CreateAX -------------------------------------------------------------------------------------*/
  785. //
  786. // We create our "X", outline it, and fill it with stars.
  787. //
  788. void CreateAX (WindowPtr wind)
  789. {
  790.     gxShape                thePage;
  791.     gxShape                tempTextShape;
  792.     gxShape             starShape;
  793.     gxRectangle         starShapeBounds;
  794.     gxPatternRecord        starPattern;
  795.     
  796.     long starGeometry[] = {    1, //  number of contours
  797.                             5, //  number of points 
  798.                               ff(60), 0, ff(90), ff(90),  ff(0), ff(30),  ff(120), ff(30), ff(0), ff(90)};   //  the points
  799.  
  800.     //
  801.     //    Retrieve the GX picture attached to the front window.
  802.     //
  803.     thePage = GetDocShape(wind);
  804.  
  805.      //
  806.     // Create a star shape which will be used as the fill pattern
  807.     //
  808.     starShape = GXNewPolygons((gxPolygons *) starGeometry);
  809.     GXSetShapeFill (starShape,  gxWindingFill);
  810.     GXScaleShape(starShape, fl(0.15), fl(0.15), 0, 0);
  811.  
  812.     //
  813.     //    Get the bounds of our star shape.  We use the bounds to setup the u and v vectors of the pattern 
  814.     //    record. We want "tempTextShape" to be filled  with the star where each star is placed at edge of the
  815.     //    previous star (i.e so the pattern's do not overlap).
  816.     //
  817.     //    We set up the pattern record to use our star shape and no attributes will be used when the filled
  818.     //    shape is drawn.
  819.     //    
  820.     GXGetShapeBounds(starShape, 0L, &starShapeBounds);
  821.  
  822.     starPattern.u.x = 0;
  823.     starPattern.u.y = starShapeBounds.bottom;
  824.     starPattern.v.x = starShapeBounds.right + fixed1;
  825.     starPattern.v.y = 0;
  826.  
  827.     starPattern.attributes = gxNoAttributes;
  828.     starPattern.pattern = starShape;
  829.  
  830.     //
  831.     //    Set the CYMK color to be magenta.
  832.     //
  833.     gTextColor.element.cmyk.cyan = 0x0000;
  834.     gTextColor.element.cmyk.magenta =  0xffff;
  835.  
  836.     gTextLocation.x += ff(65);
  837.     
  838.     //
  839.     //    Create our "X", set the transfer mode to AndMode using the transfer mode library, set the 
  840.     //    style, shape fill, shape type, and add the rotated transform.
  841.     //
  842.     //    We need to set our shape type to be path, which will allow us to fill it with stars. You can
  843.     //    only fill a shape which is a geometric shape type (i.e. you cannot fill a text shape). Also,
  844.     //    when you are filling a shape, it fills to the boundary of the geometry for the shape fill
  845.     //    specified.
  846.     //
  847.     //    The first "X" we add to the picture will be the outline of the "X", without the star shapew
  848.     //    fill.
  849.      tempTextShape = GXNewText (1, (unsigned char*) "X", &gTextLocation);
  850.      
  851.     SetShapeCommonTransfer(tempTextShape, gxCopyMode);
  852.      GXSetShapeStyle(tempTextShape, gOurStyle);
  853.     GXSetShapeType (tempTextShape, gxPathType);
  854.     GXSetShapeFill (tempTextShape, gxClosedFrameFill);
  855.     GXSetShapeTransform(tempTextShape, gRotatedTransform);
  856.  
  857.     GXSetPictureParts(thePage, 0, 0, 1, &tempTextShape, nil, nil, &gRotatedTransform);
  858.  
  859.     //
  860.     //    Set the color for the "X", set the fill to be solid, and attach the pattern record to 
  861.     //    our shape. By attaching the pattern record to our shape, adds a unique style to our
  862.     //     shape which contains the pattern record.
  863.     //
  864.     SetShapeCommonTransfer(tempTextShape, gxAndMode);
  865.     GXSetShapeColor(tempTextShape, &gTextColor);
  866.     GXSetShapeFill (tempTextShape,  gxSolidFill);
  867.     GXSetShapePattern(tempTextShape, &starPattern);
  868.     GXDisposeShape(starShape);  
  869.  
  870.     GXSetPictureParts(thePage, 0, 0, 1, &tempTextShape, nil, nil, &gRotatedTransform);
  871.     GXDisposeShape(tempTextShape);  
  872.  
  873.     //
  874.     //     Invalidate the window's portRect so that everything gets updated.
  875.     //
  876.     SetPort(wind);
  877.     InvalRect(&wind->portRect);
  878. }
  879.  
  880.  
  881.  
  882. /*------ DoCreateNew ---------------------------------------------------------------------------------*/
  883. //
  884. //    This routine is called when a window needs to be created. We create a window and add a QuickDraw GX
  885. //    gxViewPort to allow all of the QuickDraw GX drawing to occur in the correct window.
  886. //
  887. OSErr DoCreateNew(void)
  888. {
  889.     OSErr        err;
  890.     WindowPtr    wind;
  891.     
  892.     //
  893.     //     Create a window, attach a default gxViewPort to it, create and gxInitialize our privat data
  894.     //     for it, and add a sample image to its page shape.
  895.     //
  896.  
  897.     wind = NewWindow(nil, &gWindowQDRect, gWindowTitle, true, noGrowDocProc, (WindowPtr)-1L, true, 0L);
  898.     
  899.     if (!wind)
  900.         err = MemError();
  901.     else
  902.     {
  903.         GXIgnoreGraphicsNotice(transform_already_set);
  904.         SetDefaultViewPort(GXNewWindowViewPort(wind));
  905.         GXPopGraphicsNotice();
  906.         err = DoInitialization(wind);
  907.     }
  908.  
  909.     return err;
  910. }
  911.  
  912.  
  913. /*------ DoDispose -------------------------------------------------------------------------------------*/
  914. //
  915. //    This routine is called when a window needs to be disposed of.
  916. //
  917. void DoDispose(wind)
  918. WindowPtr wind;
  919. {
  920.     TH_Doc    doc;
  921.     
  922.     /**  
  923.         You should always dispose of your GX graphics objects before tossing your window. Why? It's generally good 
  924.         form and this approach guarantees that everything is disposed. If you had not disposed of everything, the
  925.         call to DisposeWindow should dispose of the objects. If you are running the debugging version of the 
  926.         SecretGraphics init with notices set, you will receive a notice that you had not disposed of everything. You
  927.         can turn notices on in this file by setting gDebugging = TRUE (above).
  928.     **/
  929.  
  930.     doc = (TH_Doc)  GetWRefCon(wind);        // Remember, this is where we stored our private data.
  931.     
  932.     GXDisposeShape(GetDocShape(wind));         // Dispose of this doc's shape.
  933.     GXDisposeJob(GetDocJob(wind));            // Dispose of this doc's print job.
  934.     DisposHandle((Handle) doc);                // Dispose of our private data.
  935.  
  936.        DisposeWindow(wind);                    // Dispose of the window.
  937. }
  938.  
  939.  
  940. /*------ DoIdle ----------------------------------------------------------------------------------------*/
  941. //
  942. //    This routine is called to do things while we're idling through tthe event loop.
  943. //
  944. void DoIdle(WindowPtr wind)
  945. {
  946. }
  947.  
  948.